package com.funkids.prxis.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.funkids.common.dto.SeckillOrderMq;
import com.funkids.prxis.entity.SysGoods;
import com.funkids.prxis.entity.SysOrder;
import com.funkids.prxis.entity.SysSeckillGoods;
import com.funkids.prxis.entity.SysSeckillOrder;
import com.funkids.prxis.mapper.SysSeckillGoodsMapper;
import com.funkids.prxis.service.ISysGoodsService;
import com.funkids.prxis.service.ISysOrderService;
import com.funkids.prxis.service.ISysSeckillGoodsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.funkids.prxis.service.ISysSeckillOrderService;
import com.funkids.rabbitmq.RMSender;
import com.funkids.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author funkids
 * @since 2023-03-22
 */
@Service
public class SysSeckillGoodsServiceImpl extends ServiceImpl<SysSeckillGoodsMapper, SysSeckillGoods> implements ISysSeckillGoodsService {

    @Autowired
    ISysSeckillOrderService sysSeckillOrderService;

    @Autowired
    ISysOrderService sysOrderService;

    @Autowired
    ISysGoodsService sysGoodsService;

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    RMSender rmSender;

    @Transactional
    @Override
    public int seckill(Long userId, Long goodsId) {

        SysSeckillGoods seckillGoods = this.getOne(new QueryWrapper<SysSeckillGoods>().eq("goods_id",goodsId));
        SysGoods goods = sysGoodsService.getById(goodsId);

        //保证一人只能秒杀一件特定商品
        boolean seckilled = redisUtils.hasKey("order:"+userId + ":" + goodsId);
        if(seckilled){
            return 2;
        }

        //判断商品库存状态，减少对预减库存的频繁操作；
        boolean isEmpty =redisUtils.hasKey("isEmpty_GoodsId:" + goodsId);
        if(isEmpty){
            return 0;
        }

        //使用redids预减库存
        Long seckillStock = redisUtils.decr("GoodsId:"+goodsId,1);
        if(seckillStock<0){
            redisUtils.incr("GoodsId:"+goodsId,1);
            redisUtils.set("isEmpty_GoodsId:"+goodsId,"1");
            return 0;
        }

        //将订单信息发送到消息队列
        SeckillOrderMq seckillOrderMq = new SeckillOrderMq(userId,goodsId);
        rmSender.sendSeckillInfo(JSONUtil.toJsonStr(seckillOrderMq));
        //更新数据库
       //seckillDB(userId,goodsId);

        //redis存储库存，用户秒杀商品关系
        redisUtils.set("order:" + userId + ":" + goodsId,0);


        return 1;
    }
    //乐观锁的配置需要在sysGooods中增加version字段

    @Transactional
    @Override
    public void seckillDB(Long userId, Long goodsId){
        SysSeckillGoods seckillGoods = this.getOne(new QueryWrapper<SysSeckillGoods>().eq("goods_id",goodsId));
        SysGoods goods = sysGoodsService.getById(goodsId);

        //对库存进行更新
        seckillGoods.setSeckillStock(seckillGoods.getSeckillStock()-1);
        goods.setGoodsStock(goods.getGoodsStock()-1);
        boolean result = this.update(new UpdateWrapper<SysSeckillGoods>().setSql("seckill_stock = seckill_stock-1").
                eq("goods_id",goodsId).gt("seckill_stock",0));
        if(!result){
            return;
        }
        //创建订单
        SysOrder sysOrder = new SysOrder();
        sysOrder.setUserId(userId);
        sysOrder.setGoodsId(goodsId);
        sysOrder.setGoodsCnt(1);
        sysOrder.setGoodsPrice(seckillGoods.getSeckillPrice());
        sysOrder.setCreateTime(LocalDateTime.now());
        sysOrder.setStatus(1);
        sysOrderService.save(sysOrder);

        //创建秒杀订单
        SysSeckillOrder sysSeckillOrder = new SysSeckillOrder();
        sysSeckillOrder.setUserId(userId);
        sysSeckillOrder.setGoodsId(goodsId);
        sysSeckillOrder.setOrderId(sysOrder.getId());
        sysSeckillOrderService.save(sysSeckillOrder);
    }

    @Override
    public Long getResult(Long userId, Long goodsId) {

        SysSeckillOrder order = sysSeckillOrderService.getOne(new QueryWrapper<SysSeckillOrder>().eq("user_id", userId).eq("goods_id", goodsId));
        if(order==null){
            boolean isEmpty =redisUtils.hasKey("isEmpty_GoodsId:" + goodsId);
            if(!isEmpty){
                return 1L;
            }else{
                return 0L;
            }
        }
        return order.getOrderId();
    }
}
